Skip to content

feat: dedup alerts so one failure = one incident#6

Merged
Lushenwar merged 1 commit into
mainfrom
feat/alert-dedup
Jul 14, 2026
Merged

feat: dedup alerts so one failure = one incident#6
Lushenwar merged 1 commit into
mainfrom
feat/alert-dedup

Conversation

@Lushenwar

Copy link
Copy Markdown
Owner

Why

Closes the noise/false-positive gap: previously every alert opened an incident and fired an LLM call + Slack card, so a spiking error meant N alerts → N incidents → N Claude calls → N Slack cards. This was the one interview answer the code genuinely didn't back.

Threshold-alone doesn't fix it (alert N+1 fires again after crossing the threshold). The real fix is open-incident dedup.

What

handle_alert now runs a sliding-window gate:

  • fire — open a new incident (default behavior for a fresh signature)
  • duplicate — a still-open signature folds into the live incident, no new incident, no LLM/Slack
  • suppress — below the burst threshold (SENTINEL_DEDUP_THRESHOLD, default 1 = fire immediately; raise to require a burst within SENTINEL_DEDUP_WINDOW_S, default 300s)

Signatures clear at every terminal state (resolved / degraded / failed-and-reverted) so later alerts reopen normally. /alert skips background diagnostics for suppressed/duplicate alerts.

Also fixed

Latent PK collision the new tests surfaced: incident IDs were timestamped only to the second, so two same-second alerts collided and ON CONFLICT DO UPDATE overwrote the first record. Added a 2-byte random suffix.

Scope notes

  • In-process dedup (per-worker, resets on restart) — marked ponytail: with the upgrade path to Postgres/Redis if you go multi-worker.
  • Response-only suppressed/duplicate shapes on /alert; stored incident schema and the /incidents contract are unchanged, so the dashboard is unaffected.

Tests

20 passed — added test_dedup_folds_repeat_alerts and test_dedup_threshold_suppresses_below_burst.

🤖 Generated with Claude Code

Previously every alert opened an incident and fired an LLM call + Slack
card, so a spiking error flooded the pipeline (N alerts -> N incidents).

Add an in-process sliding-window gate in handle_alert:
- fold repeat alerts for a still-open error signature into the live
  incident instead of opening a new one (the actual flood fix)
- configurable burst threshold (SENTINEL_DEDUP_THRESHOLD, default 1) so a
  signature can be required to fire N times in the window before triaging
- clear the signature at every terminal state (resolved / degraded /
  failed-and-reverted) so later alerts reopen normally
- /alert skips background diagnostics for suppressed/duplicate alerts

Also fixes a latent PK collision surfaced by the new tests: incident IDs
were timestamped only to the second, so two same-second alerts collided
and ON CONFLICT DO UPDATE overwrote the first. Added a random suffix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Lushenwar
Lushenwar merged commit 5b63f9b into main Jul 14, 2026
2 of 4 checks passed
Lushenwar added a commit that referenced this pull request Jul 14, 2026
The alert-dedup merge (#6) landed with two files that failed the
`black --check --line-length 110` backend gate. Formatting only — no
logic change; 20 core tests still pass.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant